//****************************************************************
//* Copyright (c) 2008 Ford Motor Company. All Rights Reserved.
//*
//* $$Workfile:   CostStructureLogic.java  $$
//* $$Revision:   1.3  $$
//* $$Author:   TMALDON4  $$
//* $$Date:   Feb 26 2009 07:30:22  $$
//*
//*****************************************************************
package ar.com.ford.it.fullEconomics.logic;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import org.apache.commons.lang.StringUtils;
import ar.com.ford.it.fullEconomics.FullEconomicsPrs;
import ar.com.ford.it.fullEconomics.exception.FullEconomicsException;
import ar.com.ford.it.fullEconomics.persistence.dao.CostStructureDao;
import ar.com.ford.it.fullEconomics.persistence.dao.EconomicIndexDefDao;
import ar.com.ford.it.fullEconomics.persistence.dao.ItemDao;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc01Coststruct;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc02Coststvers;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc03Subcoststr;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc04Subcsthier;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc06Item;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc07Subcstitem;
import ar.com.ford.it.fullEconomics.persistence.dto.Teese01Economic;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp01Part;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp02Commodity;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp04Supply;
import ar.com.ford.it.fullEconomics.persistence.dto.Teess01Supplier;
import ar.com.ford.it.fullEconomics.struct.CostStructureCreateStruct;
import ar.com.ford.it.fullEconomics.struct.CostStructureFindStruct;
import ar.com.ford.it.fullEconomics.struct.OptionCombo;
import ar.com.ford.it.fullEconomics.util.FullEconomicsDateUtil;
import ar.com.ford.it.fullEconomics.wslx.FullEconomicsWslxUser;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;
import com.ford.it.persistence.PersistenceException;

public class CostStructureLogic {

    private static final String CLASS_NAME = CostStructureLogic.class.getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(
            CLASS_NAME);

    /**
     * 
     * @return Coleccion de los tipos de fecha creacion, propuesta, aprobacion y
     * Effective Date in
     */
    public Collection<OptionCombo> getComboDateTypes() {

        String METHOD_NAME = "getComboDateTypes";
        log.entering(CLASS_NAME, METHOD_NAME);

        LinkedList<OptionCombo> list = new LinkedList<OptionCombo>();

        list.add(new OptionCombo("Creation", "Creacion"));
        list.add(new OptionCombo("Proposal", "Propuesta"));
        list.add(new OptionCombo("Approval", "Aprobacion"));
        list.add(new OptionCombo("EffDateIn", "Fecha Efectiva de entrada"));

        log.exiting(CLASS_NAME, METHOD_NAME);
        return list;
    }

    /**
     * Filtra de la coleccion pasada por parametro solo la ultima version
     * aprovada de cada estructura de costos
     * 
     * @param costStrVersions
     * @return
     */
    private Collection<Teesc02Coststvers> filterLastApprovedOnly(
                                                                 Collection<Teesc02Coststvers> costStrVersions) {
        HashMap<Integer, Teesc02Coststvers> maximums = new HashMap<Integer, Teesc02Coststvers>();
        LinkedList<Teesc02Coststvers> ret = new LinkedList<Teesc02Coststvers>();
        Teesc02Coststvers aux = null;

        for (Teesc02Coststvers version : costStrVersions) {
            aux = maximums.get(version.getTeesc01Coststruct()
                    .getEesc01CststrNumberK());
            if (aux == null) {
                if (version.getEesc02CststvApprovalUserC() != null) {
                    maximums.put(version.getTeesc01Coststruct()
                            .getEesc01CststrNumberK(), version);
                }
            } else {
                if (version.getEesc02CststvApprovalUserC() != null) {
                    if ((version.getEesc02CststvApprovalS().after(
                            aux.getEesc02CststvApprovalS()) || version
                            .getEesc02CststvApprovalS().equals(
                                    aux.getEesc02CststvApprovalS()))
                            && version.getEesc02CststvVersionNumberK() > aux
                                    .getEesc02CststvVersionNumberK()) {
                        maximums.put(version.getTeesc01Coststruct()
                                .getEesc01CststrNumberK(), version);
                    }
                }
            }
        }

        ret.addAll(maximums.values());
        return ret;
    }

    /**
     * Busca versiones de estructura de costos.
     * 
     * @param parameters
     * @return
     * @throws FullEconomicsException
     */
    public Collection findCostStructureVersions(
                                                CostStructureFindStruct parameters)
            throws FullEconomicsException {

        String METHOD_NAME = "findCostStructureVersions";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao csDao = new CostStructureDao();
        Teesc02Coststvers costStructureVersion = new Teesc02Coststvers();
        Teesc01Coststruct costStructure = new Teesc01Coststruct();
        Teess01Supplier supplier = new Teess01Supplier();
        Teesp04Supply supply = new Teesp04Supply();
        Teesp01Part part = new Teesp01Part();
        Teesp02Commodity commodity = new Teesp02Commodity();
        Timestamp dateMin = null;
        Timestamp dateMax = null;
        Collection ret = null;

        try {
            supplier.setEess01PlantCodeC(parameters.getPlant());
            if (parameters.getSupplierClass().equals("-1")) {
                supplier.setEess01SupplierClassCodeC(null);
            } else {
                supplier.setEess01SupplierClassCodeC(parameters
                        .getSupplierClass());
            }
            supplier.setEess01SupplierCodeC(parameters.getSupplierCode());
            part.setEesp01PlantCodeC(parameters.getPlant());
            if (parameters.getPartClass() == null
                    || parameters.getPartClass().equals("-1")) {
                part.setEesp01PartClassCodeC(null);
            } else {
                part.setEesp01PartClassCodeC(parameters.getPartClass());
            }
            part.setEesp01PartPrefixCodeC(parameters.getPartPrefix());
            part.setEesp01PartBaseCodeC(parameters.getPartBase());
            part.setEesp01PartSuffixCodeC(parameters.getPartSufix());
            supply.setEesp04PlantCodeC(parameters.getPlant());
            supply.setTeess01Supplier(supplier);
            supply.setTeesp01Part(part);
            commodity.setEesp02PlantCodeC(parameters.getPlant());
            if (parameters.getCommodityNumber() == null
                    || parameters.getCommodityNumber().equals("-1")) {
                commodity.setEesp02CommodityNumberK(null);
            } else {
                commodity.setEesp02CommodityNumberK(Integer.parseInt(parameters
                        .getCommodityNumber()));
            }
            costStructure.setEesc01PlantCodeC(parameters.getPlant());
            costStructure.setTeesp04Supply(supply);
            costStructure.setTeesp02Commodity(commodity);
            costStructureVersion.setEesc02PlantCodeC(parameters.getPlant());
            costStructureVersion.setTeesc01Coststruct(costStructure);
            if (StringUtils.isNotBlank(parameters.getDateMin())) {
                dateMin = new Timestamp(FullEconomicsDateUtil.format(
                        parameters.getDateMin()).getTimeInMillis());
            }
            if (StringUtils.isNotBlank(parameters.getDateMax())) {
                dateMax = new Timestamp(FullEconomicsDateUtil.format(
                        parameters.getDateMax()).getTimeInMillis());
            }

            ret = csDao.findCostStructureVersions(costStructureVersion,
                    parameters.getStatus(), parameters.getLastAppOnly(),
                    parameters.getDateType(), dateMin, dateMax, parameters
                            .getUserActionType(), parameters.getUserId());
            if (parameters.getLastAppOnly() != null) {
                ret = this.filterLastApprovedOnly(ret);
            }
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find Cost Structure Versions Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.CostStructureFind.FIND);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * Busca los Sub Cost Structure Items asociados a la Sub Cost Structure
     * pasada por parametro y si son Items asociados a Economic Indexes o no
     * (variableItems == true o false respectivamente)
     * 
     * @param subCostStructure
     * @param variableItems
     * @return
     * @throws FullEconomicsException
     */
    public Collection<Teesc07Subcstitem> findSubCostStructureItems(
                                                                   Teesc03Subcoststr subCostStructure,
                                                                   boolean variableItems)
            throws FullEconomicsException {

        String METHOD_NAME = "findSubCostStructureItems";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao costStructureDao = new CostStructureDao();
        Collection<Teesc07Subcstitem> res = null;
        Teesc07Subcstitem subCostStrItem = new Teesc07Subcstitem();
        Teesc06Item item = new Teesc06Item();

        try {
            subCostStrItem.setEesc07PlantCodeC(subCostStructure
                    .getEesc03PlantCodeC());
            subCostStrItem.setTeesc03Subcoststr(subCostStructure);
            if (variableItems) {
                item.setEesc06ItemIndexedFlagF("1");
            } else {
                item.setEesc06ItemIndexedFlagF("0");
            }
            subCostStrItem.setTeesc06Item(item);

            res = costStructureDao.findSubCostStructureItems(subCostStrItem);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find Sub Cost Structure Items Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.FIND_SUBCOSTSTRITEMS);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return res;
    }

    public Teesc03Subcoststr getIncompleteSubCostStr(Teesc03Subcoststr father)
            throws FullEconomicsException {
        String METHOD_NAME = "getIncompleteSubCostStr";
        log.entering(CLASS_NAME, METHOD_NAME);
        Teesc03Subcoststr ret = null;
        Collection<Teesc03Subcoststr> subCostStrs = this
                .findSubCostStructures(father);
        Collection<Teesc07Subcstitem> items = this.findSubCostStructureItems(
                father, true);
        items.addAll(this.findSubCostStructureItems(father, false));
        BigDecimal sum = this.getTotalSum(items, subCostStrs);
        if (sum.compareTo(new BigDecimal(100)) == -1) {
            ret = father;
        } else if (sum.compareTo(new BigDecimal(100)) == 1) {
            ret = father;
        } else {
            for (Teesc03Subcoststr son : subCostStrs) {
                ret = this.getIncompleteSubCostStr(son);
                if (ret != null)
                    break;
            }
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;

    }

    /**
     * Busca las Sub Cost Structures asociadas a la Sub Cost Structure pasada
     * por parametro
     * 
     * @param subCostStructure
     * @return
     * @throws FullEconomicsException
     */
    public Collection<Teesc03Subcoststr> findSubCostStructures(
                                                               Teesc03Subcoststr subCostStructure)
            throws FullEconomicsException {

        String METHOD_NAME = "findSubCostStructures";
        log.entering(CLASS_NAME, METHOD_NAME);

        ItemDao itemDao = new ItemDao();
        String[] fields = { "teesc03Subcoststr" };
        Object[] values = { subCostStructure };
        Collection<Teesc04Subcsthier> aux = null;
        Collection<Teesc03Subcoststr> res = new LinkedList<Teesc03Subcoststr>();

        try {
            aux = itemDao.findAll(new Teesc04Subcsthier(), fields, values);
            for (Teesc04Subcsthier hierarchy : aux) {
                res.add(hierarchy.getTeesc03Subcoststr2());
            }
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find Sub Cost Structures Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.FIND_SUBCOSTSTR);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return res;
    }

    /**
     * Da de alta una Cost Structure, una Cost Structure Version y una Sub Cost
     * Structure
     * 
     * @param costStructureCreateStruct
     * @throws FullEconomicsException
     * @return Cost Structure Version creada
     */
    public Teesc02Coststvers createCostStructure(
                                                 FullEconomicsWslxUser user,
                                                 CostStructureCreateStruct parameters)
            throws FullEconomicsException {

        String METHOD_NAME = "createCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        String[] fields = { "eesc01PlantCodeC" };
        Object[] values = { user.getTeesg01Plant() };
        Teesc01Coststruct costStructure = new Teesc01Coststruct();
        Teesc03Subcoststr subCostStr = new Teesc03Subcoststr();
        Teesc02Coststvers costStrVersion = new Teesc02Coststvers();
        Teesp04Supply supply = new Teesp04Supply();
        Teesp02Commodity commodity = new Teesp02Commodity();
        Teesp01Part part = new Teesp01Part();
        Teess01Supplier supplier = new Teess01Supplier();
        PartLogic partLogic = new PartLogic();
        CostStructureDao costStructureDao = new CostStructureDao();

        try {
            // <COST STRUCTURE>
            supplier.setEess01PlantCodeC(user.getTeesg01Plant());
            supplier.setEess01SupplierClassCodeC(parameters.getSupplierType());
            supplier.setEess01SupplierCodeC(parameters.getSupplierCode());
            supplier = (Teess01Supplier) costStructureDao.getObjById(supplier);
            costStructure.setTeess01Supplier(supplier);
            costStructure.setEesc01PlantCodeC(user.getTeesg01Plant());
            costStructure.setEesc01CststrTypeCodeC(parameters
                    .getCostStructureType());
            if (costStructure.getEesc01CststrTypeCodeC().equalsIgnoreCase("C")) {
                commodity.setEesp02PlantCodeC(user.getTeesg01Plant());
                commodity.setEesp02CommodityNumberK(Integer.parseInt(parameters
                        .getCommodityNumber()));
                costStructure.setTeesp02Commodity(commodity);
            } else if (costStructure.getEesc01CststrTypeCodeC()
                    .equalsIgnoreCase("P")) {
                supply.setEesp04PlantCodeC(user.getTeesg01Plant());
                supply.setTeess01Supplier(supplier);
                part.setEesp01PlantCodeC(user.getTeesg01Plant());
                part.setEesp01PartClassCodeC(parameters.getPartClass());
                part.setEesp01PartPrefixCodeC(parameters.getPartPrefix());
                part.setEesp01PartBaseCodeC(parameters.getPartBase());
                part.setEesp01PartSuffixCodeC(parameters.getPartSufix());
                part = partLogic.findPartByPk(part);
                supply.setTeesp01Part(part);
                supply = (Teesp04Supply) costStructureDao.getObjById(supply);
                costStructure.setTeesp04Supply(supply);
            }
            costStructure.setEesc01CreateUserC(user.getId());
            costStructure.setEesc01CreateS(new Timestamp(System
                    .currentTimeMillis()));
            costStructure.setEesc01LastUpdtUserC(user.getId());
            costStructure.setEesc01LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            costStructure.setEesc01CststrNumberK(costStructureDao.getMax(
                    new Teesc01Coststruct(), fields, values,
                    "eesc01CststrNumberK") + 1);
            // </COST STRUCTURE>

            // <SUB COST STRUCTURE>
            fields[0] = "eesc03PlantCodeC";
            values[0] = user.getTeesg01Plant();
            subCostStr.setEesc03PlantCodeC(user.getTeesg01Plant());
            subCostStr.setEesc03SubcstNumberK(costStructureDao.getMax(
                    new Teesc03Subcoststr(), fields, values,
                    "eesc03SubcstNumberK") + 1);
            subCostStr.setEesc03SubcstNameN(parameters.getDescription());
            subCostStr.setEesc03SubcstPercentP(new BigDecimal(100));
            subCostStr.setEesc03CreateUserC(user.getId());
            subCostStr.setEesc03CreateS(new Timestamp(System
                    .currentTimeMillis()));
            subCostStr.setEesc03LastUpdtUserC(user.getId());
            subCostStr.setEesc03LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            // </SUB COST STRUCTURE>

            // <COST STRUCTURE VERSION>
            String[] sFields = { "eesc02PlantCodeC", "teesc01Coststruct" };
            Object[] sValues = { user.getTeesg01Plant(), costStructure };
            Calendar aux = null;
            costStrVersion.setEesc02PlantCodeC(user.getTeesg01Plant());
            costStrVersion.setTeesc01Coststruct(costStructure);
            costStrVersion.setEesc02CststvVersionNumberK(costStructureDao
                    .getMax(new Teesc02Coststvers(), sFields, sValues,
                            "eesc02CststvVersionNumberK") + 1);
            aux = FullEconomicsDateUtil.format(parameters.getDateIn());
            costStrVersion.setEesc02CststvInDateY(new Timestamp(aux
                    .getTimeInMillis()));
            aux = FullEconomicsDateUtil.format(parameters.getDateOut());
            costStrVersion.setEesc02CststvOutDateY(new Timestamp(aux
                    .getTimeInMillis()));
            costStrVersion.setTeesc03Subcoststr(subCostStr);
            costStrVersion.setEesc02CreateUserC(user.getId());
            costStrVersion.setEesc02CreateS(new Timestamp(System
                    .currentTimeMillis()));
            costStrVersion.setEesc02LastUpdtUserC(user.getId());
            costStrVersion.setEesc02LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            costStrVersion.setEesc02CststvCommentsX(parameters
                    .getObservations());
            // FIXME Quitar siguiente linea una vez que se quite el campo status
            // de la DB. Luciano tiene que borrar el campo, pero de mientras
            // para
            // que no explote le seteo un valor
            costStrVersion.setEesc02CststvStatusCodeC("H");
            // </COST STRUCTURE VERSION>

            PersistenceUtil.newTransaction();
            costStructureDao.createCostStructure(costStructure);
            costStructureDao.createSubCostStructure(subCostStr);
            costStructureDao.createCostStructureVersion(costStrVersion);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Cost Structure Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureNew.CREATE_COSTSTR);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return costStrVersion;
    }

    /**
     * Da de alta una Sub Cost Structure, y una Sub Cost Structure Hierarchy en
     * caso de que subCostStrFather != null
     * 
     * @param user
     * @param costStrVersion
     * @param subCostStrFather
     * @param fatherTier
     * @param subCostStr
     * @throws FullEconomicsException
     */
    public void createSubCostStructure(FullEconomicsWslxUser user,
                                       Teesc02Coststvers costStrVersion,
                                       Teesc03Subcoststr subCostStrFather,
                                       int fatherTier,
                                       Teesc03Subcoststr subCostStr)
            throws FullEconomicsException {

        String METHOD_NAME = "createSubCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesc04Subcsthier hierarchy = new Teesc04Subcsthier();
        String[] fields = new String[1];
        Object[] values = new Object[1];
        CostStructureDao costStructureDao = new CostStructureDao();

        try {
            fields[0] = "eesc03PlantCodeC";
            values[0] = user.getTeesg01Plant();
            subCostStr.setEesc03PlantCodeC(user.getTeesg01Plant());
            subCostStr.setEesc03SubcstNumberK(costStructureDao.getMax(
                    new Teesc03Subcoststr(), fields, values,
                    "eesc03SubcstNumberK") + 1);
            subCostStr.setEesc03CreateUserC(user.getId());
            subCostStr.setEesc03CreateS(new Timestamp(System
                    .currentTimeMillis()));
            subCostStr.setEesc03LastUpdtUserC(user.getId());
            subCostStr.setEesc03LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));

            if (subCostStrFather != null) {
                hierarchy.setEesc04PlantCodeC(user.getTeesg01Plant());
                hierarchy.setTeesc02Coststvers(costStrVersion);
                hierarchy.setTeesc03Subcoststr(subCostStrFather);
                hierarchy.setTeesc03Subcoststr2(subCostStr);
                hierarchy.setEesc04Scsthr1TierCodeC(fatherTier);
                hierarchy.setEesc04Scsthr2TierCodeC(fatherTier + 1);
                hierarchy.setEesc04CreateUserC(user.getId());
                hierarchy.setEesc04CreateS(new Timestamp(System
                        .currentTimeMillis()));
                hierarchy.setEesc04LastUpdtUserC(user.getId());
                hierarchy.setEesc04LastUpdtS(new Timestamp(System
                        .currentTimeMillis()));
            }

            PersistenceUtil.newTransaction();
            costStructureDao.createSubCostStructure(subCostStr);
            if (subCostStrFather != null) {
                costStructureDao.createHierarchy(hierarchy);
            }
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Sub Cost Structure Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.CREATE_SUBCOSTSTR);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Crea un Sub Cost Structure Item. Tanto el porcentaje como la Sub Cost
     * Structure a la que pertenece el Item deben venir dentro del Sub Cost
     * Structure Item pasado por parametro.
     * 
     * @param user
     * @param subCostStrItem
     * @param itemNumber
     * @param economicIndexNumber
     * @throws FullEconomicsException
     */
    public void createSubCostStrItem(FullEconomicsWslxUser user,
                                     Teesc07Subcstitem subCostStrItem,
                                     String itemNumber,
                                     String economicIndexNumber)
            throws FullEconomicsException {

        String METHOD_NAME = "createSubCostStrItem";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao costStructureDao = new CostStructureDao();
        ItemDao itemDao = new ItemDao();
        Teesc06Item item = new Teesc06Item();
        Teese01Economic economicIndex = new Teese01Economic();

        try {
            item.setEesc06PlantCodeC(user.getTeesg01Plant());
            item.setEesc06ItemNumberK(Integer.parseInt(itemNumber));
            item = (Teesc06Item) itemDao.getObjById(item);
            subCostStrItem.setEesc07PlantCodeC(user.getTeesg01Plant());
            subCostStrItem.setTeesc06Item(item);
            if (item.getEesc06ItemIndexedFlagF().equals("1")) {
                economicIndex.setEese01PlantCodeC(user.getTeesg01Plant());
                economicIndex.setEese01EconNumberK(Integer
                        .parseInt(economicIndexNumber));
                subCostStrItem.setTeese01Economic(economicIndex);
            }
            subCostStrItem.setEesc07CreateUserC(user.getId());
            subCostStrItem.setEesc07CreateS(new Timestamp(System
                    .currentTimeMillis()));
            subCostStrItem.setEesc07LastUpdtUserC(user.getId());
            subCostStrItem.setEesc07LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            PersistenceUtil.newTransaction();
            costStructureDao.createSubCostStrItem(subCostStrItem);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Sub Cost Structure Item Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.CREATE_SUBCOSTSTRITEM);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);

    }

    /**
     * Actualiza la Sub Cost Structure pasada por parametro
     * 
     * @param user
     * @param subCostStr
     * @throws FullEconomicsException
     */
    public void updateSubCostStructure(FullEconomicsWslxUser user,
                                       Teesc03Subcoststr subCostStr)
            throws FullEconomicsException {
        String METHOD_NAME = "updateSubCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesc03Subcoststr workingCopy = null;
        CostStructureDao dao = new CostStructureDao();
        Teesc03Subcoststr newValues = new Teesc03Subcoststr();
        Teess01Supplier supplier = null;
        Teesp04Supply supply = new Teesp04Supply();

        try {
            PersistenceUtil.newTransaction();
            // Tengo que poner los nuevos valores en otro objeto si o si porque
            // sino no hace el update porque el getObjForUpdate hace algo con la
            // referencia que le paso
            newValues.setEesc03SubcstNameN(subCostStr.getEesc03SubcstNameN());
            newValues.setEesc03SubcstPercentP(subCostStr
                    .getEesc03SubcstPercentP());
            if (subCostStr.getTeess01Supplier() != null) {
                if (!subCostStr.getTeess01Supplier()
                        .getEess01SupplierClassCodeC().equals("-1")) {
                    subCostStr.getTeess01Supplier().setEess01PlantCodeC(
                            user.getTeesg01Plant());
                    supplier = (Teess01Supplier) dao.getObjForUpdate(subCostStr
                            .getTeess01Supplier());
                    newValues.setTeess01Supplier(supplier);
                    subCostStr.setTeess01Supplier(null);
                    if (subCostStr.getTeesp04Supply() != null) {
                        if (!subCostStr.getTeesp04Supply().getTeesp01Part()
                                .getEesp01PartClassCodeC().equals("-1")) {
                            supply = subCostStr.getTeesp04Supply();
                            supply.setEesp04PlantCodeC(user.getTeesg01Plant());
                            supply = (Teesp04Supply) dao
                                    .getObjForUpdate(supply);
                            newValues.setTeesp04Supply(supply);
                            subCostStr.setTeesp04Supply(null);
                        }
                    }
                }
            }
            workingCopy = (Teesc03Subcoststr) dao.getObjForUpdate(subCostStr);
            workingCopy.setEesc03SubcstNameN(newValues.getEesc03SubcstNameN());
            workingCopy.setEesc03SubcstPercentP(newValues
                    .getEesc03SubcstPercentP());
            if (newValues.getTeess01Supplier() != null) {
                workingCopy.setTeess01Supplier(newValues.getTeess01Supplier());
            }
            if (newValues.getTeesp04Supply() != null) {
                workingCopy.setTeesp04Supply(newValues.getTeesp04Supply());
            }
            workingCopy.setEesc03LastUpdtUserC(user.getId());
            workingCopy.setEesc03LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Update Sub Cost Struture Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.UPDATE_SUBCOSTSTR);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * 
     * @param user
     * @param subCostStrItem
     * @param itemNumber
     * @param economicIndexNumber
     * @throws FullEconomicsException
     */
    public void updateSubCostStrItem(FullEconomicsWslxUser user,
                                     Teesc07Subcstitem subCostStrItem,
                                     String itemNumber,
                                     String economicIndexNumber)
            throws FullEconomicsException {
        String METHOD_NAME = "updateSubCostStrItem";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao costStructureDao = new CostStructureDao();
        ItemDao itemDao = new ItemDao();
        EconomicIndexDefDao economicDao = new EconomicIndexDefDao();
        Teesc06Item item = new Teesc06Item();
        Teese01Economic economicIndex = new Teese01Economic();
        Teesc07Subcstitem workingCopy = null;
        Teesc07Subcstitem newValues = new Teesc07Subcstitem();

        try {
            newValues.setEesc07ScstitmPercentP(subCostStrItem
                    .getEesc07ScstitmPercentP());
            PersistenceUtil.newTransaction();
            workingCopy = (Teesc07Subcstitem) costStructureDao
                    .getObjForUpdate(subCostStrItem);
            workingCopy.setEesc07ScstitmPercentP(newValues
                    .getEesc07ScstitmPercentP());
            item.setEesc06PlantCodeC(user.getTeesg01Plant());
            item.setEesc06ItemNumberK(Integer.parseInt(itemNumber));
            item = (Teesc06Item) itemDao.getObjForUpdate(item);

            workingCopy.setTeesc06Item(item);
            if (item.getEesc06ItemIndexedFlagF().equals("1")) {
                economicIndex.setEese01PlantCodeC(user.getTeesg01Plant());
                economicIndex.setEese01EconNumberK(Integer
                        .parseInt(economicIndexNumber));
                economicIndex = (Teese01Economic) economicDao
                        .getObjForUpdate(economicIndex);
                workingCopy.setTeese01Economic(economicIndex);
            }
            workingCopy.setEesc07LastUpdtUserC(user.getId());
            workingCopy.setEesc07LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Update Sub Cost Structure Item Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.UPDATE_SUBCOSTSTRITEM);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Comprueba si el numero de Item pasado por parametro ya existe en alguno
     * de los Sub Cost Structure Items contenidos en la coleccion pasada por
     * parametro
     * 
     * @param subCostStrItems
     * @param itemNumber
     * @return
     */
    public boolean subCostStrItemAlreadyExists(
                                               Collection<Teesc07Subcstitem> subCostStrItems,
                                               String itemNumber) {
        String METHOD_NAME = "subCostStrItemAlreadyExists";
        log.entering(CLASS_NAME, METHOD_NAME);

        Integer itemNbr = Integer.parseInt(itemNumber);
        boolean ret = false;

        for (Teesc07Subcstitem subCostStrItem : subCostStrItems) {
            if (subCostStrItem.getTeesc06Item().getEesc06ItemNumberK().equals(
                    itemNbr)) {
                ret = true;
            }
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * Comprueba que en la coleccion de Sub Cost Structures no exista una Sub
     * Cost Structure con el nombre pasado por parametro (subCsName)
     * 
     * @param subCostStructures
     * @param subCsName
     * @return
     */
    public boolean subCostStrNameAlreadyExists(
                                               Collection<Teesc03Subcoststr> subCostStructures,
                                               String subCsName) {
        String METHOD_NAME = "subCostStrNameAlreadyExists";
        log.entering(CLASS_NAME, METHOD_NAME);

        boolean ret = false;

        for (Teesc03Subcoststr subCostStr : subCostStructures) {
            if (subCostStr.getEesc03SubcstNameN().equalsIgnoreCase(
                    subCsName.trim())) {
                ret = true;
            }
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * Elimina el Sub Cost Structure Item pasado por parametro
     * 
     * @param subCostStrItem
     * @throws FullEconomicsException
     */
    public void deleteSubCostStrItem(Teesc07Subcstitem subCostStrItem)
            throws FullEconomicsException {

        String METHOD_NAME = "deleteSubCostStrItem";
        log.entering(CLASS_NAME, METHOD_NAME);

        try {
            PersistenceUtil.newTransaction();
            CostStructureDao dao = new CostStructureDao();
            dao.deleteSubCostStrItem(subCostStrItem);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Delete Sub Cost Structure Item Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.DELETE_SUBCOSTSTRITEM);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Elimina recursivamente la Sub Cost Structure pasada por parametro
     * 
     * @param subCostStr
     * @param costStrVersion
     * @throws FullEconomicsException
     * @throws PersistenceException
     */
    private void recursiveDeleteSubCostStr(Teesc03Subcoststr subCostStr,
                                           Teesc02Coststvers costStrVersion,
                                           boolean deleteRoot, int level)
            throws FullEconomicsException, PersistenceException {
        Collection<Teesc07Subcstitem> subCostStrItems = null;
        Collection<Teesc03Subcoststr> subCostStructures = null;
        CostStructureDao dao = new CostStructureDao();
        Teesc04Subcsthier hierarchy = null;

        // Primero borro todos los items contenidos en la Sub Cost Structure
        subCostStrItems = this.findSubCostStructureItems(subCostStr, true);
        subCostStrItems.addAll(this
                .findSubCostStructureItems(subCostStr, false));
        for (Teesc07Subcstitem subCostStrItem : subCostStrItems) {
            PersistenceUtil.newTransaction();
            this.deleteSubCostStrItem(subCostStrItem);
            PersistenceUtil.commitTransaction();
        }

        // Ahora borro las Sub Cost Structures que tenga
        subCostStructures = this.findSubCostStructures(subCostStr);
        for (Teesc03Subcoststr subCostStrSon : subCostStructures) {
            recursiveDeleteSubCostStr(subCostStrSon, costStrVersion,
                    deleteRoot, level + 1);
        }

        // Finalmente borro las jerarquias que correspondan
        // Busco la jerarquia, que es unica para la costStrVersion y subCostStr
        // buscada como hijo
        hierarchy = dao.findHierarchyBySon(subCostStr, costStrVersion);
        if (hierarchy != null) {
            PersistenceUtil.newTransaction();
            dao.deleteHierarchy(hierarchy);
            PersistenceUtil.commitTransaction();
        }

        // Finalmente borro la Sub Cost Structure
        if (level == 0) {
            if (deleteRoot) {
                PersistenceUtil.newTransaction();
                dao.deleteSubCostStr(subCostStr);
                PersistenceUtil.commitTransaction();
            }
        } else {
            PersistenceUtil.newTransaction();
            dao.deleteSubCostStr(subCostStr);
            PersistenceUtil.commitTransaction();
        }
    }

    /**
     * Elimina la Sub Cost Structure pasada por parametro y todos sus hijos.
     * Elimina ademas las jerarquias que correspondan
     * 
     * @param subCostStr
     * @throws FullEconomicsException
     */
    public void deleteSubCostStr(Teesc03Subcoststr subCostStr,
                                 Teesc02Coststvers costStrVersion)
            throws FullEconomicsException {

        String METHOD_NAME = "deleteSubCostStr";
        log.entering(CLASS_NAME, METHOD_NAME);

        try {
            this.recursiveDeleteSubCostStr(subCostStr, costStrVersion, true, 0);
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Delete Sub Cost Structure Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureDef.DELETE_SUBCOSTSTR);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Calcula la suma de los porcentajes de los Sub Cost Structure Items mas
     * los porcentajes de las Sub Cost Structures
     * 
     * @param subCostStrItems
     * @param subCostStructures
     * @return
     */
    public BigDecimal getTotalSum(
                                  Collection<Teesc07Subcstitem> subCostStrItems,
                                  Collection<Teesc03Subcoststr> subCostStructures) {

        String METHOD_NAME = "getTotalSum";
        log.entering(CLASS_NAME, METHOD_NAME);

        BigDecimal total = new BigDecimal(0);

        for (Teesc07Subcstitem subCostStrItem : subCostStrItems) {
            total = total.add(subCostStrItem.getEesc07ScstitmPercentP());
        }
        for (Teesc03Subcoststr subCostStr : subCostStructures) {
            total = total.add(subCostStr.getEesc03SubcstPercentP());
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return total;
    }

    /**
     * Crea copias de las Sub Cost Structures contenidas en la Sub Cost
     * Structure pasada por parametro, y tambien de los Sub Cost Structure Items
     * 
     * @param user
     * @param subCostStr
     * @throws FullEconomicsException
     * @throws PersistenceException
     */
    private void recursiveCopySubCostStr(FullEconomicsWslxUser user,
                                         Teesc03Subcoststr subCostStr,
                                         Teesc03Subcoststr subCostStrFather,
                                         Teesc02Coststvers costStrVersion,
                                         int tier)
            throws FullEconomicsException, PersistenceException {
        Collection<Teesc07Subcstitem> subCostStrItems = null;
        Collection<Teesc03Subcoststr> subCostStructures = null;

        // Primero busco todos los items contenidos en la Sub Cost Structure
        subCostStrItems = this.findSubCostStructureItems(subCostStr, true);
        subCostStrItems.addAll(this
                .findSubCostStructureItems(subCostStr, false));

        // Ahora busco las Sub Cost Structures que tenga
        subCostStructures = this.findSubCostStructures(subCostStr);

        // Despues del siguiente if ya tengo la subCostStr con el id
        // nuevo
        if (subCostStrFather != null) {
            PersistenceUtil.newTransaction();
            this.createSubCostStructure(user, costStrVersion, subCostStrFather,
                    tier, subCostStr);
            PersistenceUtil.commitTransaction();
        } else {
            subCostStr = costStrVersion.getTeesc03Subcoststr();
        }

        for (Teesc03Subcoststr subCostStrSon : subCostStructures) {
            recursiveCopySubCostStr(user, subCostStrSon, subCostStr,
                    costStrVersion, tier + 1);
        }

        for (Teesc07Subcstitem subCostStrItem : subCostStrItems) {
            String itemNumber = subCostStrItem.getTeesc06Item()
                    .getEesc06ItemNumberK().toString();
            String economicIndexNumber = null;

            if (subCostStrItem.getTeesc06Item().getEesc06ItemIndexedFlagF()
                    .equals("1")) {
                economicIndexNumber = subCostStrItem.getTeesc06Item()
                        .getTeese01Economic().getEese01EconNumberK().toString();
            }
            subCostStrItem.setTeesc03Subcoststr(subCostStr);

            PersistenceUtil.newTransaction();
            this.createSubCostStrItem(user, subCostStrItem, itemNumber,
                    economicIndexNumber);
            PersistenceUtil.commitTransaction();
        }
    }

    /**
     * Crea una Sub Cost Structure que sera la principal para una version, por
     * lo tanto no da de alta jerarquias. Debe tener el porcentaje seteado
     * 
     * @param subCostStr
     * @return
     * @throws PersistenceException
     */
    private Teesc03Subcoststr createPrincipalSubCostStructure(
                                                              FullEconomicsWslxUser user,
                                                              Teesc03Subcoststr subCostStr)
            throws PersistenceException {
        String METHOD_NAME = "createPrincipalSubCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao dao = new CostStructureDao();
        String[] fields = { "eesc03PlantCodeC" };
        Object[] values = { user.getTeesg01Plant() };
        Teesc03Subcoststr newSubCostStr = new Teesc03Subcoststr();

        newSubCostStr.setEesc03PlantCodeC(user.getTeesg01Plant());
        newSubCostStr
                .setEesc03SubcstNumberK(dao.getMax(new Teesc03Subcoststr(),
                        fields, values, "eesc03SubcstNumberK") + 1);
        newSubCostStr.setEesc03SubcstNameN(subCostStr.getEesc03SubcstNameN());
        newSubCostStr.setEesc03SubcstPercentP(subCostStr
                .getEesc03SubcstPercentP());
        newSubCostStr.setTeesp04Supply(subCostStr.getTeesp04Supply());

        newSubCostStr.setTeess01Supplier(subCostStr.getTeess01Supplier());

        newSubCostStr.setEesc03CreateUserC(user.getId());
        newSubCostStr
                .setEesc03CreateS(new Timestamp(System.currentTimeMillis()));
        newSubCostStr.setEesc03LastUpdtUserC(user.getId());
        newSubCostStr.setEesc03LastUpdtS(new Timestamp(System
                .currentTimeMillis()));

        PersistenceUtil.newTransaction();
        dao.createSubCostStructure(newSubCostStr);
        PersistenceUtil.commitTransaction();

        log.exiting(CLASS_NAME, METHOD_NAME);
        return newSubCostStr;
    }

    /**
     * Crea una nueva version de la Cost Structure Version pasada por parametro
     * 
     * @param user
     * @param version
     * @return
     * @throws FullEconomicsException
     */
    public Teesc02Coststvers createNewCostStructureVersion(
                                                           FullEconomicsWslxUser user,
                                                           Teesc02Coststvers version)
            throws FullEconomicsException {

        String METHOD_NAME = "createNewCostStructureVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesc02Coststvers newVersion = new Teesc02Coststvers();
        Teesc03Subcoststr subCostStrPrincipal = null;
        CostStructureDao dao = new CostStructureDao();
        String[] fields = { "eesc02PlantCodeC", "teesc01Coststruct" };
        Object[] values = { user.getTeesg01Plant(),
                version.getTeesc01Coststruct() };

        try {
            newVersion.setEesc02PlantCodeC(user.getTeesg01Plant());
            newVersion.setTeesc01Coststruct(version.getTeesc01Coststruct());
            newVersion.setEesc02CststvVersionNumberK(dao.getMax(
                    new Teesc02Coststvers(), fields, values,
                    "eesc02CststvVersionNumberK") + 1);
            newVersion.setEesc02CststvInDateY(version.getEesc02CststvInDateY());
            newVersion.setEesc02CststvOutDateY(version
                    .getEesc02CststvOutDateY());
            newVersion.setEesc02CststvCommentsX(version
                    .getEesc02CststvCommentsX());
            newVersion.setEesc02CststvStatusCodeC(version
                    .getEesc02CststvStatusCodeC());

            // Atencion: el createPrincipalSubCostStructure NO DEBE AFECTAR AL
            // QUE LE PASO POR PARaMETRO y debe devolver el creado.
            subCostStrPrincipal = createPrincipalSubCostStructure(user, version
                    .getTeesc03Subcoststr());
            newVersion.setTeesc03Subcoststr(subCostStrPrincipal);

            newVersion.setEesc02CreateS(new Timestamp(System
                    .currentTimeMillis()));
            newVersion.setEesc02CreateUserC(user.getId());
            newVersion.setEesc02LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            newVersion.setEesc02LastUpdtUserC(user.getId());

            PersistenceUtil.newTransaction();
            dao.createNewCostStructureVersion(newVersion);
            PersistenceUtil.commitTransaction();

            this.recursiveCopySubCostStr(user, version.getTeesc03Subcoststr(),
                    null, newVersion, 0);
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "New Sub Cost Structure Version Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureNew.CREATE_COSTSTRVERS);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return newVersion;
    }

    /**
     * 
     * @param costStrVersion
     * @return
     */
    public boolean costStructureCanBeProposed(Teesc02Coststvers costStrVersion) {
        String METHOD_NAME = "costStructureCanBeProposed";
        log.entering(CLASS_NAME, METHOD_NAME);

        boolean ret = false;

        if (costStrVersion.getEesc02CreateUserC() != null
                && costStrVersion.getEesc02CststvProposalUserC() == null) {
            ret = true;
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * 
     * @param costStrVersion
     * @param user
     * @throws FullEconomicsException
     */
    public void proposeCostStructure(Teesc02Coststvers costStrVersion,
                                     FullEconomicsWslxUser user)
            throws FullEconomicsException {
        String METHOD_NAME = "proposeCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao dao = new CostStructureDao();
        Teesc02Coststvers workingCopy = null;
        Teesc02Coststvers pk = new Teesc02Coststvers();

        try {
            pk.setEesc02PlantCodeC(user.getTeesg01Plant());
            pk.setTeesc01Coststruct(costStrVersion.getTeesc01Coststruct());
            pk.setEesc02CststvVersionNumberK(costStrVersion
                    .getEesc02CststvVersionNumberK());

            PersistenceUtil.newTransaction();
            workingCopy = (Teesc02Coststvers) dao.getObjForUpdate(pk);
            workingCopy.setEesc02CststvProposalS(new Timestamp(System
                    .currentTimeMillis()));
            workingCopy.setEesc02CststvProposalUserC(user.getId());
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Propose Cost Structure Version Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureFind.PROPOSE_COSTSTRVERS);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * 
     * @return
     */
    public boolean costStructureCanBeApproved(Teesc02Coststvers costStrVersion,
                                              FullEconomicsWslxUser user) {
        String METHOD_NAME = "costStructureCanBeApproved";
        log.entering(CLASS_NAME, METHOD_NAME);

        boolean ret = false;

        if (costStrVersion.getEesc02CststvProposalUserC() != null
                && !costStrVersion.getEesc02CststvProposalUserC().equals(
                        user.getId())) {
            ret = true;
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * 
     * @param costStrVersion
     * @param user
     * @throws FullEconomicsException
     */
    public void approveCostStructure(Teesc02Coststvers costStrVersion,
                                     FullEconomicsWslxUser user)
            throws FullEconomicsException {
        String METHOD_NAME = "approveCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao dao = new CostStructureDao();
        Teesc02Coststvers workingCopy = null;
        Teesc02Coststvers pk = new Teesc02Coststvers();

        try {
            pk.setEesc02PlantCodeC(user.getTeesg01Plant());
            pk.setTeesc01Coststruct(costStrVersion.getTeesc01Coststruct());
            pk.setEesc02CststvVersionNumberK(costStrVersion
                    .getEesc02CststvVersionNumberK());

            PersistenceUtil.newTransaction();
            workingCopy = (Teesc02Coststvers) dao.getObjForUpdate(pk);
            workingCopy.setEesc02CststvApprovalS(new Timestamp(System
                    .currentTimeMillis()));
            workingCopy.setEesc02CststvApprovalUserC(user.getId());
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Approve Cost Structure Version Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureFind.APPROVE_COSTSTRVERS);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Crear una Cost Structure sin tener en cuenta
     * 
     * @param user
     * @param costStructure
     * @throws FullEconomicsException
     */
    private Teesc01Coststruct createSimpleCostStructure(
                                                        FullEconomicsWslxUser user,
                                                        CostStructureCreateStruct csCreateStruct)
            throws FullEconomicsException {

        String METHOD_NAME = "createSimpleCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        String[] fields = { "eesc01PlantCodeC" };
        Object[] values = { user.getTeesg01Plant() };
        Teesc01Coststruct costStructure = new Teesc01Coststruct();
        Teesp04Supply supply = new Teesp04Supply();
        Teesp02Commodity commodity = new Teesp02Commodity();
        Teesp01Part part = new Teesp01Part();
        Teess01Supplier supplier = new Teess01Supplier();
        PartLogic partLogic = new PartLogic();
        CostStructureDao costStructureDao = new CostStructureDao();

        try {
            supplier.setEess01PlantCodeC(user.getTeesg01Plant());
            supplier.setEess01SupplierClassCodeC(csCreateStruct
                    .getSupplierType());
            supplier.setEess01SupplierCodeC(csCreateStruct.getSupplierCode());
            supplier = (Teess01Supplier) costStructureDao.getObjById(supplier);
            costStructure.setTeess01Supplier(supplier);
            costStructure.setEesc01PlantCodeC(user.getTeesg01Plant());
            costStructure.setEesc01CststrTypeCodeC(csCreateStruct
                    .getCostStructureType());
            if (costStructure.getEesc01CststrTypeCodeC().equalsIgnoreCase("C")) {
                commodity.setEesp02PlantCodeC(user.getTeesg01Plant());
                commodity.setEesp02CommodityNumberK(Integer
                        .parseInt(csCreateStruct.getCommodityNumber()));
                costStructure.setTeesp02Commodity(commodity);
            } else if (costStructure.getEesc01CststrTypeCodeC()
                    .equalsIgnoreCase("P")) {
                supply.setEesp04PlantCodeC(user.getTeesg01Plant());
                supply.setTeess01Supplier(supplier);
                part.setEesp01PlantCodeC(user.getTeesg01Plant());
                part.setEesp01PartClassCodeC(csCreateStruct.getPartClass());
                part.setEesp01PartPrefixCodeC(csCreateStruct.getPartPrefix());
                part.setEesp01PartBaseCodeC(csCreateStruct.getPartBase());
                part.setEesp01PartSuffixCodeC(csCreateStruct.getPartSufix());
                part = partLogic.findPartByPk(part);
                supply.setTeesp01Part(part);
                supply = (Teesp04Supply) costStructureDao.getObjById(supply);
                costStructure.setTeesp04Supply(supply);
            }
            costStructure.setEesc01CreateUserC(user.getId());
            costStructure.setEesc01CreateS(new Timestamp(System
                    .currentTimeMillis()));
            costStructure.setEesc01LastUpdtUserC(user.getId());
            costStructure.setEesc01LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            costStructure.setEesc01CststrNumberK(costStructureDao.getMax(
                    new Teesc01Coststruct(), fields, values,
                    "eesc01CststrNumberK") + 1);

            PersistenceUtil.newTransaction();
            costStructureDao.createCostStructure(costStructure);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Simple Cost Structure Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureNew.CREATE_SIMPLE_COSTSTR);
        }

        return costStructure;
    }

    /**
     * Copia la Cost Structure Version pasada por parametro a una nueva Cost
     * Structure
     * 
     * @param user
     * @param version
     * @param csCreateStruct
     * @return
     * @throws FullEconomicsException
     */
    public Teesc02Coststvers copyCostStructureVersion(
                                                      FullEconomicsWslxUser user,
                                                      Teesc02Coststvers version,
                                                      CostStructureCreateStruct csCreateStruct)
            throws FullEconomicsException {

        String METHOD_NAME = "copyCostStructureVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesc02Coststvers newVersion = new Teesc02Coststvers();
        Teesc03Subcoststr subCostStrPrincipal = null;
        CostStructureDao dao = new CostStructureDao();
        Teesc01Coststruct costStructure = null;
        Calendar aux = null;

        try {
            costStructure = createSimpleCostStructure(user, csCreateStruct);

            newVersion.setEesc02PlantCodeC(user.getTeesg01Plant());
            newVersion.setTeesc01Coststruct(costStructure);
            aux = FullEconomicsDateUtil.format(csCreateStruct.getDateIn());
            newVersion.setEesc02CststvInDateY(new Timestamp(aux
                    .getTimeInMillis()));
            aux = FullEconomicsDateUtil.format(csCreateStruct.getDateOut());
            newVersion.setEesc02CststvOutDateY(new Timestamp(aux
                    .getTimeInMillis()));
            newVersion.setEesc02CststvVersionNumberK(1);
            newVersion.setEesc02CststvCommentsX(csCreateStruct
                    .getObservations());
            newVersion.setEesc02CststvStatusCodeC("H");

            version.getTeesc03Subcoststr().setEesc03SubcstNameN(
                    csCreateStruct.getDescription());
            subCostStrPrincipal = createPrincipalSubCostStructure(user, version
                    .getTeesc03Subcoststr());
            newVersion.setTeesc03Subcoststr(subCostStrPrincipal);

            newVersion.setEesc02CreateS(new Timestamp(System
                    .currentTimeMillis()));
            newVersion.setEesc02CreateUserC(user.getId());
            newVersion.setEesc02LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            newVersion.setEesc02LastUpdtUserC(user.getId());

            PersistenceUtil.newTransaction();
            dao.createNewCostStructureVersion(newVersion);
            PersistenceUtil.commitTransaction();

            this.recursiveCopySubCostStr(user, version.getTeesc03Subcoststr(),
                    null, newVersion, 0);
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Copy Cost Structure Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureNew.COPY_COSTSTR);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return newVersion;
    }

    /**
     * Actualiza la Cost Structure Version pasada por parametro
     * 
     * @param user
     * @param costStrVersion
     * @throws FullEconomicsException
     */
    public void updateCostStructureVersion(FullEconomicsWslxUser user,
                                           Teesc02Coststvers costStrVersion)
            throws FullEconomicsException {

        String METHOD_NAME = "updateCostStructureVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesc02Coststvers csvWorkingCopy = null;
        Teesc03Subcoststr scsWorkingCopy = null;
        Teesc02Coststvers newValuesCS = new Teesc02Coststvers();
        Teesc03Subcoststr newValuesSCS = new Teesc03Subcoststr();
        CostStructureDao dao = new CostStructureDao();

        try {
            newValuesCS.setEesc02CststvInDateY(costStrVersion
                    .getEesc02CststvInDateY());
            newValuesCS.setEesc02CststvOutDateY(costStrVersion
                    .getEesc02CststvOutDateY());
            newValuesCS.setEesc02CststvCommentsX(costStrVersion
                    .getEesc02CststvCommentsX());
            newValuesSCS.setEesc03SubcstNameN(costStrVersion
                    .getTeesc03Subcoststr().getEesc03SubcstNameN());

            PersistenceUtil.newTransaction();
            csvWorkingCopy = (Teesc02Coststvers) dao
                    .getObjForUpdate(costStrVersion);
            scsWorkingCopy = (Teesc03Subcoststr) dao
                    .getObjForUpdate(costStrVersion.getTeesc03Subcoststr());
            csvWorkingCopy.setEesc02CststvInDateY(newValuesCS
                    .getEesc02CststvInDateY());
            csvWorkingCopy.setEesc02CststvOutDateY(newValuesCS
                    .getEesc02CststvOutDateY());
            csvWorkingCopy.setEesc02CststvCommentsX(newValuesCS
                    .getEesc02CststvCommentsX());
            scsWorkingCopy.setEesc03SubcstNameN(newValuesSCS
                    .getEesc03SubcstNameN());
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Update Cost Structure Version Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureNew.UPDATE_COSTSTRVERS);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Elimina la Cost Structure Version pasada por parametro y elimina
     * recursivamente todos los elementos que contenga su Sub Cost Structure
     * principal. En caso de ser la ultima version asociada a la Cost Structure,
     * elimina tambien la Cost Structure.
     * 
     * @param user
     * @param costStrVersion
     * @throws FullEconomicsException
     * @throws PersistenceException
     */
    public void deleteSubCostStrVersion(FullEconomicsWslxUser user,
                                        Teesc02Coststvers costStrVersion)
            throws FullEconomicsException {

        String METHOD_NAME = "deleteSubCostStrVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        CostStructureDao dao = new CostStructureDao();
        Collection<Teesc02Coststvers> costStrVersions = null;
        Teesc01Coststruct costStructure = null;
        Teesc03Subcoststr subCostStr = null;
        int size = 0;
        String[] fields = { "eesc02PlantCodeC", "teesc01Coststruct" };
        Object[] values = { user.getTeesg01Plant(),
                costStrVersion.getTeesc01Coststruct() };

        try {
            subCostStr = costStrVersion.getTeesc03Subcoststr();
            costStructure = costStrVersion.getTeesc01Coststruct();
            costStrVersions = dao.findAll(new Teesc02Coststvers(), fields,
                    values);
            size = costStrVersions.size();
            this
                    .recursiveDeleteSubCostStr(subCostStr, costStrVersion,
                            false, 0);
            PersistenceUtil.newTransaction();
            dao.deleteCostStructureVersion(costStrVersion);
            dao.deleteSubCostStr(subCostStr);
            if (size == 1) {
                dao.deleteCostStructure(costStructure);
            }
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Delete Cost Structure Version Exception", e);
            throw new FullEconomicsException(
                    e,
                    FullEconomicsPrs.MessageErrors.CostStructureFind.DELETE_COSTSTRVERS);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Busca recursivamente si la subCostStr tiene algun item desaprobado
     * 
     * @param subCostStr
     * @return True si todos los Sub Cost Structure Items estan aprobados. False
     * si alguno no lo esta.
     * @throws FullEconomicsException
     */
    private boolean recursiveCheckIfAllItemsAreApproved(
                                                        Teesc03Subcoststr subCostStr)
            throws FullEconomicsException {
        boolean ret = true;
        Collection<Teesc07Subcstitem> subCostStrItems = null;
        Collection<Teesc03Subcoststr> subCostStructures = null;

        subCostStructures = this.findSubCostStructures(subCostStr);
        for (Teesc03Subcoststr subCostStrSon : subCostStructures) {
            ret = recursiveCheckIfAllItemsAreApproved(subCostStrSon);
            if (!ret) {
                break;
            }
        }

        if (ret) {
            subCostStrItems = this.findSubCostStructureItems(subCostStr, true);
            subCostStrItems.addAll(this.findSubCostStructureItems(subCostStr,
                    false));
            for (Teesc07Subcstitem subCostStrItem : subCostStrItems) {
                if (subCostStrItem.getTeesc06Item()
                        .getEesc06ItemApprovalUserC() == null) {
                    ret = false;
                    break;
                }
            }
        }

        return ret;
    }

    /**
     * Determina si todos los Items que tiene la Cost Structure Version estan
     * aprobados
     * 
     * @param costStrVersion
     * @return
     * @throws FullEconomicsException
     */
    public boolean checkIfallItemsAreApproved(Teesc02Coststvers costStrVersion)
            throws FullEconomicsException {
        String METHOD_NAME = "checkIfallItemsAreApproved";
        log.entering(CLASS_NAME, METHOD_NAME);
        boolean ret = false;

        ret = recursiveCheckIfAllItemsAreApproved(costStrVersion
                .getTeesc03Subcoststr());

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }
}
